package main

import (
	"regexp"
	"strconv"
	"strings"
	"baliance.com/gooxml/document"
	"log"
	"paper-check/model"
	"io/ioutil"
	"os"
	"fmt"
)

const (
	PAPER     = "Paper"
	SECTION   = "Section"
	NUM       = "Num"
	QUESTION  = "Question"
	SELECTION = "Selection"
	PIC       = "Pic"
	EXPLAIN   = "Explain"
)

var (
	cp     *model.Paper
	cq     *model.Question
	qs     map[int]*model.Question
	snum   int
	qmax   int
	repeat string
	oks    int
)

func main() {
	dir := "word"
	finish := "finish"
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		os.Mkdir(dir, os.ModePerm)
	}
	if _, err := os.Stat(finish); os.IsNotExist(err) {
		os.Mkdir(finish, os.ModePerm)
	}
	dirs, err := ioutil.ReadDir(dir)
	if err != nil {
		log.Fatal(err)
	}
	if len(dirs) == 0 {
		log.Fatal(dir + "文件夹为空，请将需要操作的 docx 放入该文件夹")
	}
	log.Println("请输入对应序号，来制定 docx 文件")
	for k, v := range dirs {
		log.Println(k+1, v.Name())
	}
	no := 1
	fmt.Scanln(&no)
	name := dirs[no-1].Name()
	num := WordParse(dir + "/" + name)
	if num == 0 {
		num = qmax
	}
	log.Println("定义题目", num, "实际找到", len(qs))
	WordCheck(num)

	if repeat != "" {
		log.Print("以下题号重复出现，重复出现会导致之前的题号被覆盖，请检查解析处是否缺失“解析”“答案”字眼，是否出现以数字分隔符打头的段落" + repeat)
	}

	if oks == num && repeat == "" {
		log.Println("恭喜,一个错误都没有了")
	}

	log.Println("是否移动该试卷到 " + finish + " 中？输入任意大于 0 的数字确认，直接回车取消")
	yes := 0
	fmt.Scanln(&yes)
	if yes > 0 {
		if err := os.Rename(dir+"/"+name, finish+"/"+name); err != nil {
			log.Println(err)
		}
	}
}

func WordCheck(num int) bool {
	log.Println("正在检查....请确保最大的题号正确，将会以该题号作为题目总数")
	for i := 1; i <= num; i++ {
		q := qs[i]
		//log.Println(q)
		if q == nil {
			log.Println("No.", i, "该题缺失，请检查题号及分隔符，或者题干出现“解析”“答案”字眼，替换为“解答”之类均可")
			continue
		}
		res := ""
		if q.Stem == "" {
			res += "题干缺失 "
		}
		if len(q.Selections) < 4 {
			res += "选项缺失 "
			if q.Selections["A"] == "" {
				res += "A "
			}
			if q.Selections["B"] == "" {
				res += "B "
			}
			if q.Selections["C"] == "" {
				res += "C "
			}
			if q.Selections["D"] == "" {
				res += "D "
			}
			if q.Pic != "" {
				res += "有图片 "
			}
		}
		if q.Answer == "" {
			res += "答案缺失 "
		}
		if q.Explain == "" {
			res += "解析缺失 "
		}
		if res == "" {
			res = "ok"
			oks++
		}
		log.Println("No.", i, res)
	}
	return true
}

func WordParse(name string) int {
	doc, err := document.Open(name)
	if err != nil {
		log.Fatalln(err)
	}
	num := 0
	qs = make(map[int]*model.Question)
	//doc.Paragraphs()得到包含文档所有的段落的切片
	for _, para := range doc.Paragraphs() {
		//run为每个段落相同格式的文字组成的片段
		//fmt.Println("-----------第", i, "段-------------")
		content := ""
		for _, run := range para.Runs() {
			//fmt.Print(run.Text())
			content = content + run.Text()
		}
		//contentType := switchType(content)
		content = strings.TrimLeft(content, " ")
		content = strings.TrimRight(content, " ")
		switch switchType(content) {
		case PAPER:
			parsePaper(content)
		case SECTION:
			parseSection(content)
		case NUM:
			num = parseNum(content)
		case QUESTION:
			parseQuestion(content)
		case SELECTION:
			parseSel(content)
		case PIC:
			cq.Pic = content
		case EXPLAIN:
			parseExplain(content)
		default:

		}
	}
	log.Println("板块数量", snum)
	return num
}

func switchType(content string) string {
	//strings.TrimRight(content,"")
	//fmt.Println(content)
	rePap, err := regexp.Compile(`^Paper(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	reSec, err := regexp.Compile(`^Section(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	reNum, err := regexp.Compile(`^Num(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	reQst, err := regexp.Compile(`^[0-9]{1,3}(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	rePic, err := regexp.Compile(`^http://.+?.(png|jpg|PNG|JPG|JPEG)$`)
	if err != nil {
		log.Println(err)
	}
	reSel, err := regexp.Compile(`^[A-E](\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	reExp, err := regexp.Compile(`^[0-9]{1,3}(\.|．|:|：|、|。|，|,)[A-E]?.{0,10}?(解析|答案).{0,3}[A-E]?`)
	if err != nil {
		log.Println(err)
	}
	switch {
	case rePap.MatchString(content):
		return PAPER
	case reSec.MatchString(content):
		return SECTION
	case reNum.MatchString(content):
		return NUM
	case reExp.MatchString(content):
		return EXPLAIN
	case reQst.MatchString(content):
		return QUESTION
	case reSel.MatchString(content):
		return SELECTION
	case rePic.MatchString(content):
		return PIC
	default:
		return ""
	}
}

func parsePaper(content string) {
	re, err := regexp.Compile(`^Paper(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	content = re.ReplaceAllString(content, "")
	if cp == nil {
		cp = new(model.Paper)
	}
	cp.Name = strings.TrimLeft(content, " ")
	log.Println("试卷名称", cp.Name)
}

func parseSection(content string) {
	re, err := regexp.Compile(`^Section(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	s := new(model.Section)
	content = re.ReplaceAllString(content, "")
	s.Name = strings.TrimLeft(content, " ")
	snum++
}

func parseNum(content string) int {
	re, err := regexp.Compile(`^Num(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	content = re.ReplaceAllString(content, "")
	num, err := strconv.Atoi(content)
	if err != nil {
		log.Println(err)
	}
	return num
}

func parseQuestion(content string) {
	reStem, err := regexp.Compile(`^[0-9]{1,3}(\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	q := new(model.Question)
	q.Stem = strings.TrimLeft(reStem.ReplaceAllString(content, ""), " ")
	reSpace, err := regexp.Compile(`[ ]{4,}`)
	if err != nil {
		log.Println(err)
	}
	q.Stem = reSpace.ReplaceAllString(q.Stem, "( )")
	reKey, err := regexp.Compile(`^[0-9]{1,3}`)
	if err != nil {
		log.Println(err)
	}
	keyStr := reKey.FindString(content)
	key, err := strconv.Atoi(keyStr)
	if err != nil {
		log.Println(err)
	}
	q.Id = int64(key)
	q.Selections = make(map[string]string)
	if qs[key] != nil {
		repeat += " No. " + keyStr
	}
	qs[key] = q
	cq = q
	if key > qmax {
		qmax = key
	}
}

func parseSel(content string) {
	reKey, err := regexp.Compile(`^[A-E]`)
	if err != nil {
		log.Println(err)
	}
	re, err := regexp.Compile(`^[A-E](\.|．|:|：|、|。|，|,)`)
	if err != nil {
		log.Println(err)
	}
	if cq == nil {
		return
	}
	cq.Selections[reKey.FindString(content)] = re.ReplaceAllString(content, "")
	if err != nil {
		log.Println(err)
	}
}

func parseExplain(content string) {
	reKey, err := regexp.Compile(`^[0-9]{1,3}`)
	if err != nil {
		log.Println(err)
	}
	keyStr := reKey.FindString(content)
	key, err := strconv.Atoi(keyStr)
	if err != nil {
		log.Println(err)
	}
	rePic, err := regexp.Compile(`http://.+?.(png|jpg|PNG|JPG|JPEG)$`)
	if err != nil {
		log.Println(err)
	}
	cq = qs[key]
	if cq == nil {
		return
	}
	cq.ExpPic = rePic.FindString(content)
	content = rePic.ReplaceAllString(content, "")
	reExplain, err := regexp.Compile(`^[0-9]{1,3}.*?[A-E](\.|．|:|：|、|。|，|,|)`)
	if err != nil {
		log.Println(err)
	}
	ans := reExplain.FindString(content)
	reAnswer, err := regexp.Compile(`[A-E]`)
	if err != nil {
		log.Println(err)
	}
	cq.Answer = reAnswer.FindString(ans)
	cq.Explain = strings.TrimLeft(reExplain.ReplaceAllString(content, ""), " ")
}
